﻿/**
		 * Copyright 2010 Tim Down.
		 *
		 * Licensed under the Apache License, Version 2.0 (the "License");
		 * you may not use this file except in compliance with the License.
		 * You may obtain a copy of the License at
		 *
		 *      http://www.apache.org/licenses/LICENSE-2.0
		 *
		 * Unless required by applicable law or agreed to in writing, software
		 * distributed under the License is distributed on an "AS IS" BASIS,
		 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
		 * See the License for the specific language governing permissions and
		 * limitations under the License.
		 */

		/**
		 * jshashtable
		 *
		 * jshashtable is a JavaScript implementation of a hash table. It creates a single constructor function called Hashtable
		 * in the global scope.
		 *
		 * Author: Tim Down <tim@timdown.co.uk>
		 * Version: 2.1
		 * Build date: 21 March 2010
		 * Website: http://www.timdown.co.uk/jshashtable
		 */

		var Hashtable = (function() {
			var FUNCTION = "function";

			var arrayRemoveAt = (typeof Array.prototype.splice == FUNCTION) ?
				function(arr, idx) {
					arr.splice(idx, 1);
				} :

				function(arr, idx) {
					var itemsAfterDeleted, i, len;
					if (idx === arr.length - 1) {
						arr.length = idx;
					} else {
						itemsAfterDeleted = arr.slice(idx + 1);
						arr.length = idx;
						for (i = 0, len = itemsAfterDeleted.length; i < len; ++i) {
							arr[idx + i] = itemsAfterDeleted[i];
						}
					}
				};

			function hashObject(obj) {
				var hashCode;
				if (typeof obj == "string") {
					return obj;
				} else if (typeof obj.hashCode == FUNCTION) {
					// Check the hashCode method really has returned a string
					hashCode = obj.hashCode();
					return (typeof hashCode == "string") ? hashCode : hashObject(hashCode);
				} else if (typeof obj.toString == FUNCTION) {
					return obj.toString();
				} else {
					try {
						return String(obj);
					} catch (ex) {
						// For host objects (such as ActiveObjects in IE) that have no toString() method and throw an error when
						// passed to String()
						return Object.prototype.toString.call(obj);
					}
				}
			}

			function equals_fixedValueHasEquals(fixedValue, variableValue) {
				return fixedValue.equals(variableValue);
			}

			function equals_fixedValueNoEquals(fixedValue, variableValue) {
				return (typeof variableValue.equals == FUNCTION) ?
					   variableValue.equals(fixedValue) : (fixedValue === variableValue);
			}

			function createKeyValCheck(kvStr) {
				return function(kv) {
					if (kv === null) {
						throw new Error("null is not a valid " + kvStr);
					} else if (typeof kv == "undefined") {
						throw new Error(kvStr + " must not be undefined");
					}
				};
			}

			var checkKey = createKeyValCheck("key"), checkValue = createKeyValCheck("value");

			/*----------------------------------------------------------------------------------------------------------------*/

			function Bucket(hash, firstKey, firstValue, equalityFunction) {
				this[0] = hash;
				this.entries = [];
				this.addEntry(firstKey, firstValue);

				if (equalityFunction !== null) {
					this.getEqualityFunction = function() {
						return equalityFunction;
					};
				}
			}

			var EXISTENCE = 0, ENTRY = 1, ENTRY_INDEX_AND_VALUE = 2;

			function createBucketSearcher(mode) {
				return function(key) {
					var i = this.entries.length, entry, equals = this.getEqualityFunction(key);
					while (i--) {
						entry = this.entries[i];
						if ( equals(key, entry[0]) ) {
							switch (mode) {
								case EXISTENCE:
									return true;
								case ENTRY:
									return entry;
								case ENTRY_INDEX_AND_VALUE:
									return [ i, entry[1] ];
							}
						}
					}
					return false;
				};
			}

			function createBucketLister(entryProperty) {
				return function(aggregatedArr) {
					var startIndex = aggregatedArr.length;
					for (var i = 0, len = this.entries.length; i < len; ++i) {
						aggregatedArr[startIndex + i] = this.entries[i][entryProperty];
					}
				};
			}

			Bucket.prototype = {
				getEqualityFunction: function(searchValue) {
					return (typeof searchValue.equals == FUNCTION) ? equals_fixedValueHasEquals : equals_fixedValueNoEquals;
				},

				getEntryForKey: createBucketSearcher(ENTRY),

				getEntryAndIndexForKey: createBucketSearcher(ENTRY_INDEX_AND_VALUE),

				removeEntryForKey: function(key) {
					var result = this.getEntryAndIndexForKey(key);
					if (result) {
						arrayRemoveAt(this.entries, result[0]);
						return result[1];
					}
					return null;
				},

				addEntry: function(key, value) {
					this.entries[this.entries.length] = [key, value];
				},

				keys: createBucketLister(0),

				values: createBucketLister(1),

				getEntries: function(entries) {
					var startIndex = entries.length;
					for (var i = 0, len = this.entries.length; i < len; ++i) {
						// Clone the entry stored in the bucket before adding to array
						entries[startIndex + i] = this.entries[i].slice(0);
					}
				},

				containsKey: createBucketSearcher(EXISTENCE),

				containsValue: function(value) {
					var i = this.entries.length;
					while (i--) {
						if ( value === this.entries[i][1] ) {
							return true;
						}
					}
					return false;
				}
			};

			/*----------------------------------------------------------------------------------------------------------------*/

			// Supporting functions for searching hashtable buckets

			function searchBuckets(buckets, hash) {
				var i = buckets.length, bucket;
				while (i--) {
					bucket = buckets[i];
					if (hash === bucket[0]) {
						return i;
					}
				}
				return null;
			}

			function getBucketForHash(bucketsByHash, hash) {
				var bucket = bucketsByHash[hash];

				// Check that this is a genuine bucket and not something inherited from the bucketsByHash's prototype
				return ( bucket && (bucket instanceof Bucket) ) ? bucket : null;
			}

			/*----------------------------------------------------------------------------------------------------------------*/

			function Hashtable(hashingFunctionParam, equalityFunctionParam) {
				var that = this;
				var buckets = [];
				var bucketsByHash = {};

				var hashingFunction = (typeof hashingFunctionParam == FUNCTION) ? hashingFunctionParam : hashObject;
				var equalityFunction = (typeof equalityFunctionParam == FUNCTION) ? equalityFunctionParam : null;

				this.put = function(key, value) {
					checkKey(key);
					checkValue(value);
					var hash = hashingFunction(key), bucket, bucketEntry, oldValue = null;

					// Check if a bucket exists for the bucket key
					bucket = getBucketForHash(bucketsByHash, hash);
					if (bucket) {
						// Check this bucket to see if it already contains this key
						bucketEntry = bucket.getEntryForKey(key);
						if (bucketEntry) {
							// This bucket entry is the current mapping of key to value, so replace old value and we're done.
							oldValue = bucketEntry[1];
							bucketEntry[1] = value;
						} else {
							// The bucket does not contain an entry for this key, so add one
							bucket.addEntry(key, value);
						}
					} else {
						// No bucket exists for the key, so create one and put our key/value mapping in
						bucket = new Bucket(hash, key, value, equalityFunction);
						buckets[buckets.length] = bucket;
						bucketsByHash[hash] = bucket;
					}
					return oldValue;
				};

				this.get = function(key) {
					checkKey(key);

					var hash = hashingFunction(key);

					// Check if a bucket exists for the bucket key
					var bucket = getBucketForHash(bucketsByHash, hash);
					if (bucket) {
						// Check this bucket to see if it contains this key
						var bucketEntry = bucket.getEntryForKey(key);
						if (bucketEntry) {
							// This bucket entry is the current mapping of key to value, so return the value.
							return bucketEntry[1];
						}
					}
					return null;
				};

				this.containsKey = function(key) {
					checkKey(key);
					var bucketKey = hashingFunction(key);

					// Check if a bucket exists for the bucket key
					var bucket = getBucketForHash(bucketsByHash, bucketKey);

					return bucket ? bucket.containsKey(key) : false;
				};

				this.containsValue = function(value) {
					checkValue(value);
					var i = buckets.length;
					while (i--) {
						if (buckets[i].containsValue(value)) {
							return true;
						}
					}
					return false;
				};

				this.clear = function() {
					buckets.length = 0;
					bucketsByHash = {};
				};

				this.isEmpty = function() {
					return !buckets.length;
				};

				var createBucketAggregator = function(bucketFuncName) {
					return function() {
						var aggregated = [], i = buckets.length;
						while (i--) {
							buckets[i][bucketFuncName](aggregated);
						}
						return aggregated;
					};
				};

				this.keys = createBucketAggregator("keys");
				this.values = createBucketAggregator("values");
				this.entries = createBucketAggregator("getEntries");

				this.remove = function(key) {
					checkKey(key);

					var hash = hashingFunction(key), bucketIndex, oldValue = null;

					// Check if a bucket exists for the bucket key
					var bucket = getBucketForHash(bucketsByHash, hash);

					if (bucket) {
						// Remove entry from this bucket for this key
						oldValue = bucket.removeEntryForKey(key);
						if (oldValue !== null) {
							// Entry was removed, so check if bucket is empty
							if (!bucket.entries.length) {
								// Bucket is empty, so remove it from the bucket collections
								bucketIndex = searchBuckets(buckets, hash);
								arrayRemoveAt(buckets, bucketIndex);
								delete bucketsByHash[hash];
							}
						}
					}
					return oldValue;
				};

				this.size = function() {
					var total = 0, i = buckets.length;
					while (i--) {
						total += buckets[i].entries.length;
					}
					return total;
				};

				this.each = function(callback) {
					var entries = that.entries(), i = entries.length, entry;
					while (i--) {
						entry = entries[i];
						callback(entry[0], entry[1]);
					}
				};

				this.putAll = function(hashtable, conflictCallback) {
					var entries = hashtable.entries();
					var entry, key, value, thisValue, i = entries.length;
					var hasConflictCallback = (typeof conflictCallback == FUNCTION);
					while (i--) {
						entry = entries[i];
						key = entry[0];
						value = entry[1];

						// Check for a conflict. The default behaviour is to overwrite the value for an existing key
						if ( hasConflictCallback && (thisValue = that.get(key)) ) {
							value = conflictCallback(key, thisValue, value);
						}
						that.put(key, value);
					}
				};

				this.clone = function() {
					var clone = new Hashtable(hashingFunctionParam, equalityFunctionParam);
					clone.putAll(that);
					return clone;
				};
			}

			return Hashtable;
		})();
	
	
		// Функция установки значения cookie.
		// name - имя cookie
		// value - значение cookie
		// [path] - путь, для которого cookie действительно (по умолчанию - /)
		// [expires] - дата окончания действия cookie (по умолчанию - до конца сессии)
		// [domain] - домен, для которого cookie действительно (по умолчанию - домен,
		// в котором значение было установлено)
		// [secure] - логическое значение, показывающее требуется ли защищенная
		// передача значения cookie
		function setCookie(name, value, path, expires, domain, secure) {
			var curCookie = name + "=" + escape(value) +
			((expires) ? "; expires=" + expires.toGMTString() : "") +
			((path) ? "; path=" + path : "; path=/") +
			((domain) ? "; domain=" + domain : "") +
			((secure) ? "; secure" : "");
			document.cookie = curCookie;
		}

		// Функция чтения значения cookie.
		// name - имя считываемого cookie
		function getCookie(name) {
			var prefix = name + "=";
			var cookieStartIndex = document.cookie.indexOf(prefix);
			if(cookieStartIndex == -1) return null;
			var cookieEndIndex = document.cookie.indexOf(";", cookieStartIndex + prefix.length);
			if(cookieEndIndex == -1) cookieEndIndex = document.cookie.length;
			return unescape(document.cookie.substring(cookieStartIndex + prefix.length, cookieEndIndex));
		}

		// Функция удаления значения cookie
		// name - имя cookie
		// [path] - путь, для которого cookie действительно
		// [domain] - домен, для которого cookie действительно
		function delCookie(name, path, domain) {
			if(getCookie(name)) {
			document.cookie = name + "=" +
			((path) ? "; path=" + path : "; path=/") +
			((domain) ? "; domain=" + domain : "") +
			"; expires=Thu, 01-Jan-70 00:00:01 GMT";
			}
		}

		// Устанавливает Cookie сложной структуры.
		function setCookieEx(name, value, path, expires, domain, secure)
		{ 
			value=Serialize(value);
			// alert(value);
			return setCookie(name, value, path, expires, domain, secure);
		}

		// Читает Cookie сложной структуры.
		function getCookieEx(name)
		{ 
			var v=getCookie(name);
			return Unserialize(v);
		}


		//Сереализация/распаковка, совместимая с Perl-модулем CGI::WebIn.

		// Разделители для сериализации (те же, что в CGI::WebIn)
		var Div1 = '.';
		var Div2 = '.';

		// Функция сериализации, совместимая с CGI::WebIn::Serialize
		// Вложенные ссылки игнорируются.
		function Serialize(v)
		{ 
			return "L1"+Div1+SerializeWO(v);
		}

		// Функция десериализации.
		// Вложенные ссылки игнорируются.
		function Unserialize(v)
		{ 
			var sb=new StringBuffer(v);
			if(sb.first(1)=='L') sb.shiftTill(Div2);
			return UnserializeWO(sb);
		}

		function UnserializeWO(sb)
		{
			if(sb.first(1)=='r') sb.shift(1);
			var type=sb.first(1);
			if(type=='L' || type=='H') {
			// Массив
			sb.shift(1);
			if(sb.first(1)=='L') sb.shift(1);
			var n=sb.shiftTill(Div2);
			var len = parseInt(n);
			var a=new Array(len);
			for(var i=0; i<len; i++) {
			a[i]=UnserializeWO(sb);
			}
			// если хэш, то преобразуем
			if(type=='H') {
			var h=new Hashtable();
			for(var i=0; i<a.length; i+=2) h[a[i]]=a[i+1];
			return h;
			} else {
			return a;
			}
			} else {
			// Строка
			var n=sb.shiftTill(Div1);
			var len = parseInt(n);
			var s=sb.shift(len);
			return s;
			}
		}

		function SerializeWO(v)
		{
			if (v==null || typeof v=='number' || typeof v=='string') 
			{
				if(v==null) v="";
				return (""+v).length+Div1+(""+v);
			} 
			else if(v instanceof Array) 
			{
				var s="rL"+v.length+Div2;
				for(var i=0; i<v.length; i++) 
				{
					s+=SerializeWO(v[i]);
				}
				return s;
			} 
			else 
			{
				var a=new Array();
				for(var k in v) {
				if(v[k]==null) continue;
				a[a.length++]=k;
				a[a.length++]=v[k];
				}
				var s="rHL"+a.length+Div2;
				for(var i=0; i<a.length; i++) 
				{
					s+=SerializeWO(a[i]);
				}
				return s;
			}
		}

		// Строковой буфер с возможностью сдвига влево.
		function StringBuffer(s)
		{ 
		this.s=''+s;
		this.shift=StringBuffer_shift;
		this.shiftTill=StringBuffer_shiftTill;
		this.first=StringBuffer_first;
		}

		function StringBuffer_shift(n)
		{ 
			var s=this.s.substr(0,n);
			this.s=this.s.substr(n);
			return s;
		}

		function StringBuffer_shiftTill(s)
		{ 
			var p=this.s.indexOf(s);
			var r=this.shift(p);
			this.shift((""+s).length);
			return r;
		}

		function StringBuffer_first(n)
		{ 
			return this.s.substr(0,n);
		}
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		

		
		
	//bezier__visual_object.base.events['aaaa'] = function(){
	//	alert('!!!!');
	//}
	
		bezier__visual_object.base.bind('add_section', function(){
				//add_section(p1,p2,p3)/////////////////////////////////////////////////////////////
				//
					//console.log(arguments[0]);
					var p1 = arguments[0].p1;
					var p2 = arguments[0].p2;
					var p3 = arguments[0].p3;
					
					var l1_sid = 'line_base_points__'+this.sid+'__'+getRandomInt(100000,999999);
					var l2_sid = 'line_base_points__'+this.sid+'__'+getRandomInt(100000,999999);
					var c1_sid = 'circle_base_points__'+this.sid+'__'+getRandomInt(100000,999999);
					var c2_sid = 'circle_base_points__'+this.sid+'__'+getRandomInt(100000,999999);
					var c3_sid = 'circle_base_points__'+this.sid+'__'+getRandomInt(100000,999999);
					
					this.main_container.add({ 
								sid: l1_sid, 
								type: 'line', 	
								points: [p1, p2], 
								stroke: true,  
								strokeColor: '#000000',
					})
					.add({ 
								sid: l2_sid, 
								type: 'line', 	
								points: [p2, p3], 
								stroke: true,  
								strokeColor: '#000000',
					})
					.add({ 
								sid: c1_sid, 
								type: 'circle', 	
								points: [p1], 
								stroke: true,  
								strokeColor: '#000000',
					})
					.add({ 
								sid: c2_sid, 
								type: 'circle', 	
								points: [p2], 
								stroke: true,  
								strokeColor: '#000000',
					})
					.add({ 
								sid: c3_sid, 
								type: 'circle', 	
								points: [p3], 
								stroke: true,  
								strokeColor: '#000000',
					})
					
					
					this.linked['controls'] = this.main_container.find('%base_points__'+this.sid+'__%');
				//
				//add_section(p1,p2,p3/////////////////////////////////////////////////////////////
		});
		bezier__visual_object.base.bind('load', function(){
			//console.log('load: ', this.sid);
		});
		bezier__visual_object.base.bind('save', function(){
			//console.log('save: ', this);
			var result = [];
			for( var key in  this.points )//перебираем все точки, ибо из-за ссылок - her_base и прочих возникает зацикливание рекурсии
			{
				result.push({x: this.points[key].x, y: this.points[key].y});
			}
			//console.log('save: ', this, result);
			return { points: result, type: this.type, sid: this.sid };
		});
		bezier__visual_object.base.exec = function( event_sid, event_params ){ //тоже самое что trigger, но возвращает значение функции, а не коллекцию 		
			//console.log(this);
			if(this)
				if(this.events)
					if(this.events[event_sid])
					{
						if(event_params)
						{
							if( event_params instanceof Array) 
								return this.events[event_sid].apply( this, event_params ); 
							else
								return this.events[event_sid].apply( this, [event_params] ); 
						}
						else
							return this.events[event_sid].apply( this );
					}
					else if(this.__proto__)//если этого события нету в текущем классе, тогда ищем в родительском (потом надо будет унифицировать EXEC)
					        if(this.__proto__.events[event_sid])
							{
								if(event_params)
								{
									if( event_params instanceof Array) 
										return this.__proto__.events[event_sid].apply( this, event_params ); 
									else
										return this.__proto__.events[event_sid].apply( this, [event_params] ); 
								}
								else
									return this.__proto__.events[event_sid].apply( this );
							}
		};
	
		var esb = new esboza(document.getElementById('canvas_demo')); 
		esb.exec = function( event_sid, event_params ){//тоже самое что trigger, но возвращает значение функции, а не коллекцию
		 
			if(this)
				if(this.events)
					if(this.events[event_sid])
					{
						if(event_params)
						{
							if( event_params instanceof Array) 
								return this.events[event_sid].apply( this, event_params ); 
							else
								return this.events[event_sid].apply( this, [event_params] ); 
						}
						else
							return this.events[event_sid].apply( this );
					}
		};
		esb.bind('make_dialog', function(){//конструктор всплывающего окна диалога
		
				//console.log(arguments);
								
				var $menu = $('<div class="menu"></div>').css({'position':'fixed', 'display':'block','z-index':'10000','left':(arguments[0].position.x+this.canvas_offset.left)+'px','top':(arguments[0].position.y+this.canvas_offset.top)+'px'});
				var $div, $a;
				for( var item in arguments[0].config )
				{
					$div = $('<div style="margin: 0pt 0pt 2px;"></div>');
					$a = $('<a href="#">'+arguments[0].config[item].name+'</a>');
					
					//$a.click( arguments[0][item].action );// без явного указания контекста выполнения
					$a.click(function(local_arguments){// c указанием контекста выполнения
											return function(){
																local_arguments.action.apply( local_arguments.context ); 
																$menu.remove();
																return false;
											}
					}(arguments[0].config[item]) );
					
					$div.append($a);
					$menu.append($div);
				}
			
				
				$menu.appendTo('body');
				
				return false;
		});
		esb.bind('make_window', function(){//конструктор всплывающего окна диалога
		
				//console.log(arguments);
								
				var $window = $('<div class="window"></div>').css({'position':'fixed', 'display':'block','z-index':'10000','left':(arguments[0].position.x+this.canvas_offset.left)+'px','top':(arguments[0].position.y+this.canvas_offset.top)+'px'});
				var $div, $a;
				for( var item in arguments[0].config )
				{
					$div = $('<div style="margin: 0pt 0pt 2px;"></div>');
					$a = $('<a href="#">'+arguments[0].config[item].name+'</a>');
					
					//$a.click( arguments[0][item].action );// без явного указания контекста выполнения
					$a.click(function(local_arguments){// c указанием контекста выполнения
											return function(){
																local_arguments.action.apply( local_arguments.context ); 
																$window.remove();
																return false;
											}
					}(arguments[0].config[item]) );
					
					$div.append($a);
					$window.append($div);
				}
			
				
				$window.appendTo('body');
				
				return false;
		});
		esb.bind('load', function(){//берёт сериализованный массив объектов и загружает его
		
				var objects = Unserialize("L1.rL2.rHL6.6.pointsrL9.rHL4.1.x3.1991.y3.343rHL4.1.x3.1331.y3.292rHL4.1.x2.671.y3.241rHL4.1.x3.2831.y3.107rHL4.1.x3.3971.y3.107rHL4.1.x3.5111.y3.107rHL4.1.x3.7121.y3.244rHL4.1.x3.6561.y3.292rHL4.1.x3.6001.y3.3404.type6.bezier3.sid18.bezier_line_203148rHL6.6.pointsrL12.rHL4.1.x5.128.51.y3.675rHL4.1.x5.128.51.y3.600rHL4.1.x5.128.51.y3.525rHL4.1.x5.165.51.y3.454rHL4.1.x5.401.51.y3.454rHL4.1.x5.637.51.y3.454rHL4.1.x5.797.51.y3.481rHL4.1.x5.797.51.y3.583rHL4.1.x5.797.51.y3.685rHL4.1.x5.542.51.y3.726rHL4.1.x5.395.51.y3.726rHL4.1.x5.248.51.y3.7264.type6.bezier3.sid18.bezier_line_769516");//из сериализованной строки получаем массив объектов	
				var objects = Unserialize("L1.rL2.rHL6.6.pointsrL15.rHL4.1.x5.209.51.y3.166rHL4.1.x4.63.51.y3.166rHL4.1.x4.74.51.y3.301rHL4.1.x4.91.51.y3.502rHL4.1.x5.109.51.y3.679rHL4.1.x5.188.51.y3.701rHL4.1.x5.225.51.y3.711rHL4.1.x5.314.51.y3.736rHL4.1.x5.396.51.y3.713rHL4.1.x5.441.51.y3.702rHL4.1.x5.519.51.y3.677rHL4.1.x5.534.51.y3.513rHL4.1.x5.553.51.y3.309rHL4.1.x5.565.51.y3.166rHL4.1.x5.419.51.y3.1664.type6.bezier3.sid18.bezier_line_342171rHL6.6.pointsrL9.rHL4.1.x3.1281.y2.27rHL4.1.x3.1101.y2.27rHL4.1.x3.1101.y2.61rHL4.1.x3.1091.y2.93rHL4.1.x3.1101.y3.122rHL4.1.x3.1231.y3.123rHL4.1.x3.1311.y3.123rHL4.1.x3.1411.y3.122rHL4.1.x3.1411.y3.1044.type6.bezier3.sid18.bezier_line_441401");//из сериализованной строки получаем массив объектов	
				var objects = Unserialize("L1.rL1.rHL6.6.pointsrL15.rHL4.1.x5.242.51.y3.167rHL4.1.x4.63.51.y3.167rHL4.1.x4.80.51.y3.355rHL4.1.x4.93.51.y3.509rHL4.1.x5.109.51.y3.678rHL4.1.x5.180.51.y3.699rHL4.1.x5.232.51.y3.713rHL4.1.x5.313.51.y3.736rHL4.1.x5.390.51.y3.715rHL4.1.x5.451.51.y3.698rHL4.1.x5.518.51.y3.679rHL4.1.x5.534.51.y3.518rHL4.1.x5.549.51.y3.353rHL4.1.x5.566.51.y3.166rHL4.1.x5.384.51.y3.1664.type6.bezier3.sid18.bezier_line_911333");//из сериализованной строки получаем массив объектов	
				var objects = Unserialize("L1.rL6.rHL6.6.pointsrL15.rHL4.1.x5.804.51.y3.167rHL4.1.x5.625.51.y3.167rHL4.1.x5.642.51.y3.355rHL4.1.x5.655.51.y3.509rHL4.1.x5.671.51.y3.678rHL4.1.x5.742.51.y3.699rHL4.1.x5.794.51.y3.713rHL4.1.x5.875.51.y3.736rHL4.1.x5.952.51.y3.715rHL4.1.x6.1013.51.y3.698rHL4.1.x6.1080.51.y3.679rHL4.1.x6.1096.51.y3.518rHL4.1.x6.1111.51.y3.353rHL4.1.x6.1128.51.y3.166rHL4.1.x5.946.51.y3.1664.type6.bezier3.sid18.bezier_line_911333rHL6.6.pointsrL12.rHL4.1.x5.714.51.y3.439rHL4.1.x5.715.51.y3.241rHL4.1.x5.794.51.y3.240rHL4.1.x5.840.51.y3.240rHL4.1.x5.920.51.y3.241rHL4.1.x5.904.51.y3.410rHL4.1.x5.891.51.y3.567rHL4.1.x5.880.51.y3.677rHL4.1.x5.823.51.y3.693rHL4.1.x5.781.51.y3.706rHL4.1.x5.712.51.y3.726rHL4.1.x5.713.51.y3.5494.type6.bezier3.sid18.bezier_line_350270rHL6.6.pointsrL12.rHL4.1.x5.536.51.y3.770rHL4.1.x5.536.51.y3.745rHL4.1.x5.603.51.y3.745rHL4.1.x5.635.51.y3.745rHL4.1.x5.693.51.y3.745rHL4.1.x5.691.51.y3.767rHL4.1.x5.690.51.y3.785rHL4.1.x5.686.51.y3.810rHL4.1.x5.632.51.y3.809rHL4.1.x5.594.51.y3.810rHL4.1.x5.537.51.y3.810rHL4.1.x5.537.51.y3.7904.type6.bezier3.sid18.bezier_line_161562rHL6.6.pointsrL24.rHL4.1.x5.507.51.y3.462rHL4.1.x5.506.51.y3.438rHL4.1.x5.551.51.y3.438rHL4.1.x5.593.51.y3.437rHL4.1.x5.652.51.y3.437rHL4.1.x5.647.51.y3.494rHL4.1.x5.641.51.y3.562rHL4.1.x5.634.51.y3.631rHL4.1.x5.592.51.y3.642rHL4.1.x5.552.51.y3.654rHL4.1.x5.506.51.y3.666rHL4.1.x5.507.51.y3.642rHL4.1.x5.507.51.y3.625rHL4.1.x5.506.51.y3.602rHL4.1.x5.538.51.y3.592rHL4.1.x5.554.51.y3.589rHL4.1.x5.575.51.y3.581rHL4.1.x5.577.51.y3.554rHL4.1.x5.578.51.y3.526rHL4.1.x5.579.51.y3.500rHL4.1.x5.550.51.y3.500rHL4.1.x5.530.51.y3.500rHL4.1.x5.506.51.y3.500rHL4.1.x5.506.51.y3.4804.type6.bezier3.sid18.bezier_line_341610rHL6.6.pointsrL24.rHL4.1.x5.162.51.y3.335rHL4.1.x5.157.51.y3.271rHL4.1.x5.220.51.y3.271rHL4.1.x5.269.51.y3.270rHL4.1.x5.317.51.y3.270rHL4.1.x5.317.51.y3.299rHL4.1.x5.316.51.y3.314rHL4.1.x5.316.51.y3.335rHL4.1.x5.287.51.y3.335rHL4.1.x5.254.51.y3.334rHL4.1.x5.226.51.y3.334rHL4.1.x5.228.51.y3.359rHL4.1.x5.229.51.y3.377rHL4.1.x5.231.51.y3.398rHL4.1.x5.264.51.y3.398rHL4.1.x5.282.51.y3.399rHL4.1.x5.314.51.y3.399rHL4.1.x5.314.51.y3.419rHL4.1.x5.315.51.y3.437rHL4.1.x5.314.51.y3.462rHL4.1.x5.275.51.y3.462rHL4.1.x5.219.51.y3.461rHL4.1.x5.174.51.y3.461rHL4.1.x5.169.51.y3.4074.type6.bezier3.sid18.bezier_line_523867rHL6.6.pointsrL18.rHL4.1.x5.180.51.y3.530rHL4.1.x5.177.51.y3.493rHL4.1.x5.198.51.y3.493rHL4.1.x5.219.51.y3.492rHL4.1.x5.239.51.y3.493rHL4.1.x5.240.51.y3.513rHL4.1.x5.242.51.y3.531rHL4.1.x5.243.51.y3.543rHL4.1.x5.269.51.y3.550rHL4.1.x5.284.51.y3.553rHL4.1.x5.314.51.y3.562rHL4.1.x5.315.51.y3.587rHL4.1.x5.314.51.y3.603rHL4.1.x5.314.51.y3.627rHL4.1.x5.271.51.y3.616rHL4.1.x5.235.51.y3.604rHL4.1.x5.185.51.y3.591rHL4.1.x5.182.51.y3.5534.type6.bezier3.sid18.bezier_line_831742");//из сериализованной строки получаем массив объектов	
				
				//var objects = Unserialize(serialized_objects);//из сериализованной строки получаем массив объектов	
				for( var key in objects )
				{
						this.add( objects[key] );
						if(objects[key].type == 'bezier')
						{
								var base_bezier_obj = this.find(objects[key].sid).eq(0);
								
								base_bezier_obj.bind('drag',  function(params){ 
																		//console.log('bind("drag")');
																		var params = arguments[0];
																		for( var key in  this.points )//перебираем все точки
																		{
																			this.points[key].x += params.delta_x;
																			this.points[key].y += params.delta_y;
																		}
																		
																		this.please_render();
								})/*.bind('focus', function(){
																alert('focus');
								}).bind('blur', function(){
																alert('blur');
								})*/.bind('mousedown', function(){
																//console.log('[[[[mousedoun]]]] на объект -> '+this.sid);
																
																//для всех тех кто был выделен, и не является текущим объектом, вызываем 'unselected' 
																this.main_container.buffers['selected']
																.find( '!'+this.sid )//выбираем все выделенный объекты, не являющиеся текущим
																.each(function(){
																					this.trigger('unselected');//вызываем для них 'unselected'  
																}).each(function(){
																					this.main_container.buffers['selected'].remove(this.sid); //и удаляем их из буфера  buffers['selected']
																});
																
																
																//если он не 'selected'
																if( this.main_container.buffers['selected'].find( this.sid ).length == 0  )
																{
																	// -тогда вызываем 'selected' 
																	this.main_container.buffers['selected'] = new collection();	
																	this.main_container.buffers['selected'].push(this);
																	this.trigger('selected');
																}
																//else
																//{
																//		/* -а если он уже 'selected', то неделаем ничего */
																//}
																
																this.stop_event_for_other_object('mousedown');
																
								}).bind('selected', function(){
																console.log('[[[[selected]]]] на объект -> '+this.sid);
																//показать контролы
																//this.main_container.find('circle_base_points__'+this.sid+'__'+'%')
																this.linked['controls'].each(function(){ this.set_style('visible', true)});
																
																//this.main_container.find('line_base_points__'+this.sid+'__'+'%')
																this.linked['controls'].each(function(){ this.set_style('visible', true)});
																
																this.please_render();
								}).bind('unselected', function(){
																console.log('[[[[unselected]]]] на объект -> '+this.sid);
																//скрыть контролы
																//this.main_container.find('circle_base_points__'+this.sid+'__'+'%')
																this.linked['controls'].each(function(){ this.set_style('visible', false)});
																
																//this.main_container.find('line_base_points__'+this.sid+'__'+'%')
																this.linked['controls'].each(function(){ this.set_style('visible', false)});
																
																this.please_render();
								}).bind('mouseup_right', function(){
																
												var pos_x = arguments[0].x;
												var pos_y = arguments[0].y;
												this.main_container.trigger('make_dialog',{	
																								config:[
																											{
																												name: 'Заливка',
																												action: function(){
																																		//this.main_container.trigger('make_window', { position:{ x:pos_x, y:pos_y } });	
																																		console.log(this);
																																		var esb_obj = this;
																																		
																																		var $menu = $('<div></div>')
																																		.css({'position':'fixed', 'display':'block','z-index':'10000','left':(pos_x+this.main_container.canvas_offset.left)+'px','top':(pos_y+this.main_container.canvas_offset.top)+'px'})
																																		.appendTo('body');
																																		
																																		$menu.ColorPicker({
																																			color: '#0000ff',
																																			onShow: function (colpkr) {
																																				$(colpkr).fadeIn(500);
																																				return false;
																																			},
																																			onHide: function (colpkr) {
																																				$(colpkr).fadeOut(500);
																																				console.log( arguments );
																																				return false;
																																			},
																																			onChange: function (hsb, hex, rgb) {
																																				$('#colorSelector div').css('backgroundColor', '#' + hex);
																																				
																																				esb_obj.set_style('fillStyle','#' + hex).please_render();
																																				console.log(esb_obj);
																																			}
																																		}).ColorPickerShow();
																												},
																												context: this,
																											},
																											{
																												name: 'Граница',
																												action: function(){
																																		if( this.points[0].is_first_side_point )
																																		{ this.points[0].her_base._STD_ASIMMETRIC = true;	}
																																		else if( this.points[0].is_base )
																																		{ this.points[0]._STD_ASIMMETRIC = true; }
																																		else if( this.points[0].is_second_side_point )
																																		{ this.points[0].her_base._STD_ASIMMETRIC = true; } 
																												},
																												context: this,
																											},
																											{
																												name: 'Удалить',
																												action: function(){ /*alert('Удалить');*/ },
																												context: this,
																											},
																								], 
																								position:{ 
																											x:pos_x, 
																											y:pos_y, 
																								}
												});				
																
								});
								
								for(var pt = 0;  pt<base_bezier_obj.points.length; pt++ )
								{
								
										base_bezier_obj.trigger('add_section',{p1:base_bezier_obj.points[pt], p2:base_bezier_obj.points[pt+1], p3:base_bezier_obj.points[pt+2]});
										pt+=2;
								}
								
								
								this.find('circle_base_points__%')
								.bind('mouseup_right', esboza_studio.actions['bezier']['base_points']['mouseup_right'])
								.bind('mouseover', esboza_studio.actions['bezier']['base_points']['mouseover'])
								.bind('mouseout', esboza_studio.actions['bezier']['base_points']['mouseout'])
								.bind('drag', esboza_studio.actions['bezier']['bind_drag_to_point'] )
								.each(function(){ this.set_style('visible', false)});
								
						}
				}

				this.each(function(){ this.please_render(); });
		});
		esb.bind('save', function(){//функция возвращает сериализованный массив с данными объектов (из этих данных в последствии можно будет восставновить эти объекты)
		
			var serialized_objects = '';
			var result = [];
			
			this.each(function(){
					if( this.type == 'bezier' )
					{
							//в принципе здесь можно не проверять, ибо Безье всегда рабочий объект
							//if( this.status['worked'] )//выгружаем только рабочие объекты
							result.push( this.exec('save') );//в качестве параметра функции сохранения передаётся сам рабочий объект
					}
			});
			
			//console.log('result', result);
			serialized_objects = Serialize(result);//переводим массив с объектами в строку
			//console.log('Unserialize(serialized_objects)',Unserialize(serialized_objects));
			return serialized_objects;
		});
		
		
		


	// использование Math.round() даст неравномерное распределение!
	function getRandomInt(min, max){
	
	  return Math.floor(Math.random() * (max - min + 1)) + min;
	}
								
	
	esb.trigger('render');
	var esboza_studio = new function(){
	
		var local_this = this;
		
		this.actions = [];
		this.actions['bezier'] = [];
		this.actions['bezier']['bind_drag_to_point'] = function(){
				//console.log("this.actions['bezier']['bind_drag_to_point']", this);
				
				var params = arguments[0];
				if( this.points[0].is_base )
				{
						this.points[0].x += params.delta_x;
						this.points[0].y += params.delta_y;
						if( this.points[0].her_first_side_point )
						{   this.points[0].her_first_side_point.x += params.delta_x;
							this.points[0].her_first_side_point.y += params.delta_y;	}
						if( this.points[0].her_second_side_point )
						{	this.points[0].her_second_side_point.x += params.delta_x;
							this.points[0].her_second_side_point.y += params.delta_y;	}
				}
				if( this.points[0].is_first_side_point )
				{
						this.points[0].x += params.delta_x;
						this.points[0].y += params.delta_y;
						if( !this.points[0].her_base._STD_ASIMMETRIC ){//если точка не является симметричной
								if( this.points[0].her_second_side_point )
								{	this.points[0].her_second_side_point.x -= params.delta_x;
									this.points[0].her_second_side_point.y -= params.delta_y;	}
						}
				}
				if( this.points[0].is_second_side_point )
				{
						this.points[0].x += params.delta_x;
						this.points[0].y += params.delta_y; 
						if( !this.points[0].her_base._STD_ASIMMETRIC ){//если точка не является симметрично
							if( this.points[0].her_first_side_point )
							{   this.points[0].her_first_side_point.x -= params.delta_x;
								this.points[0].her_first_side_point.y -= params.delta_y;	}
						}
				}

				this.please_render();
		}	
		this.actions['bezier']['add_point'] = function(){
		
			//console.log(this.buffers['selected']);
			if( this.buffers['selected'].length > 0 ) 
			{
				//если буфер selected не пуст, тогда длбавляем новые точки в объект который находится в this.buffers['selected']
				//console.log('buffers[\'selected\'] НЕПУСТ ');
				
			}
			else
			{
					//если буфер selected пуст, тогда создаём новый объект, в который будем добавлять точки, а чтобы они туда добавлялись, этот объект помещаем в буфер this.buffers['selected']
					console.log('buffers[\'selected\'] ПУСТ, добавляем новый элемент');
							
							
					var local_sid = getRandomInt(100000,999999);
					esb.add({ 
						sid: 'bezier_line_'+local_sid, 
						type: 'bezier', 
						points: esboza_studio.model['bezier']['bezier_line_'+local_sid], 
						stroke: true,  
						strokeColor: '#000000',
					}).trigger('render');
					
					esb
					.find('bezier_line_'+local_sid)
					.bind('click',  function(params){ 
															//console.log( 'для объекта ' + this.sid + ' сработала функция обработчик для события "click"  с координатами:  x:'  + params.x + ', y:' + params.y);		
															//console.log( 'mouseOUT' + params.x + ' ' + params.y);
															//console.log('params',params);
															
															this.set_style('strokeStyle','#446688');
															this.set_style('fillStyle','#ffee88');
															this.please_render();
															
															this.main_container.buffers['selected'] = new collection();	
															this.main_container.buffers['selected'].push(this);	
															//this.linked['controls'].each(function(){	//для выделенных объектов показываем контролы управления
															//	this.status['VISIBLE'] = true;
															//});
					})
					.bind('drag',  function(params){ 
															//console.log('bind("drag")');
															var params = arguments[0];
															for( var key in  this.points )//перебираем все точки
															{
																this.points[key].x += params.delta_x;
																this.points[key].y += params.delta_y;
															}
															
															this.please_render();
					});
					
					this.buffers['selected'] = new collection();	
					this.buffers['selected'] = esb.find('bezier_line_'+local_sid);	
			}

			//для выделенного объекта добавляем точки
			this.buffers['selected'].each(function(local_arguments){ return function(){
			
					//console.log('esb -> buffers -> selected');
					//console.log(local_arguments);
					var p1 = { x:local_arguments[0].x, y:local_arguments[0].y, };
					var p2 = { x:local_arguments[0].x, y:local_arguments[0].y, };
					var p3 = { x:local_arguments[0].x, y:local_arguments[0].y, };
					
					this.points.push(p1); 
					this.points.push(p2); 
					this.points.push(p3); 
					this.update_property();
					
					this.trigger('add_section',{p1:p1, p2:p2, p3:p3});
					
					var all_points = this.main_container.find('circle_base_points__%')
					.bind('mouseup_right', local_this.actions['bezier']['base_points']['mouseup_right'])
					.bind('mouseover', local_this.actions['bezier']['base_points']['mouseover'])
					.bind('mouseout', local_this.actions['bezier']['base_points']['mouseout'])
					.bind('drag', local_this.actions['bezier']['bind_drag_to_point'] );
					
					all_points.get(all_points.length-1).each(function(){ /*console.log('this.sid',this.sid);*/ this.main_container.buffers['mousedown'] = new collection(); this.main_container.buffers['mousedown'].push(this); })
											
				}
			}(arguments));
		};
		this.actions['bezier']['base_points'] = Array();
		this.actions['bezier']['base_points']['mouseup_right'] = function(){ 
					
							this.main_container.trigger('make_dialog',{	
																			config:[
																					{
																						name: 'Сделать асиммертичной точкой',
																						action: function(){
																												if( this.points[0].is_first_side_point )
																												{ this.points[0].her_base._STD_ASIMMETRIC = true;	}
																												else if( this.points[0].is_base )
																												{ this.points[0]._STD_ASIMMETRIC = true; }
																												else if( this.points[0].is_second_side_point )
																												{ this.points[0].her_base._STD_ASIMMETRIC = true; } 
																						},
																						context: this,
																					},
																					{
																						name: 'Удалить',
																						action: function(){ /*alert('Удалить');*/ },
																						context: this,
																					},
																					{
																						name: 'Сделать параллельной точкой',
																						action: function(){ /*alert('Сделать параллельной точкой');*/ },
																						context: this,
																					},
																			], 
																			position:{ 
																					x:arguments[0].x, 
																					y:arguments[0].y, 
																			}
							});
		};
		this.actions['bezier']['base_points']['mouseover'] = function(params){ 
																					//console.log( 'mouseOVER' + params.x + ' ' + params.y);
													
																					this.set_style({strokeStyle:'#eeee44', fillStyle:'#ee66ee'});
																					this.please_render();

																					this.bind('animate',function(){  //функция анимации      
																																																																			
																						if( this.radius >= 10 ) { this.unbind('animate'); return this; }
																						
																						this.radius+=2; 
																						this.please_render();
																					});
		};
		this.actions['bezier']['base_points']['mouseout'] = function(params){ 
																					//console.log( 'для объекта ' + this.sid + ' сработала функция обработчик для события "mouseOUT"  с координатами:  x:'  + params.x + ', y:' + params.y);		
																					//console.log( 'mouseOUT' + params.x + ' ' + params.y);
																					//console.log('params',params);
																					
																					this.set_style('strokeStyle','#006688');
																					this.set_style('fillStyle','#880088');
																					this.please_render();
																					
																					this.bind('animate',function(){  //функция анимации      
																																																																			
																						if( this.radius <= 4 ) { this.unbind('animate'); return this; }
																						
																						this.radius-=2; 
																						this.please_render();
																					});	
		}
		this.model = [];
		this.model['bezier'] = [];
	};	
	
	//var saved_data = <?= /* .... */?>
	//esboza_studio.actions['load']( saved_data );

	////загружаем сохранившийся объект
	////esboza_studio.actions['load']('L1.rL1.rHL6.4.datarL9.rHL4.1.x3.1431.y3.375rHL4.1.x3.1331.y3.292rHL4.1.x3.1231.y3.209rHL4.1.x3.2641.y3.161rHL4.1.x3.3631.y3.180rHL4.1.x3.4621.y3.199rHL4.1.x3.4971.y3.325rHL4.1.x3.4411.y3.373rHL4.1.x3.3851.y3.4214.type6.bezier3.sid18.bezier_line_203148');
	////esboza_studio.actions['load']("L1.rL2.rHL6.4.datarL9.rHL4.1.x3.1991.y3.343rHL4.1.x3.1331.y3.292rHL4.1.x2.671.y3.241rHL4.1.x3.2831.y3.107rHL4.1.x3.3971.y3.107rHL4.1.x3.5111.y3.107rHL4.1.x3.7121.y3.244rHL4.1.x3.6561.y3.292rHL4.1.x3.6001.y3.3404.type6.bezier3.sid18.bezier_line_203148rHL6.4.datarL12.rHL4.1.x5.128.51.y3.675rHL4.1.x5.128.51.y3.600rHL4.1.x5.128.51.y3.525rHL4.1.x5.165.51.y3.454rHL4.1.x5.401.51.y3.454rHL4.1.x5.637.51.y3.454rHL4.1.x5.797.51.y3.481rHL4.1.x5.797.51.y3.583rHL4.1.x5.797.51.y3.685rHL4.1.x5.542.51.y3.726rHL4.1.x5.395.51.y3.726rHL4.1.x5.248.51.y3.7264.type6.bezier3.sid18.bezier_line_769516");
	//esboza_studio.actions['load']("L1.rL2.rHL6.4.datarL9.rHL4.1.x3.1991.y3.343rHL4.1.x3.1331.y3.292rHL4.1.x2.671.y3.241rHL4.1.x3.2831.y3.107rHL4.1.x3.3971.y3.107rHL4.1.x3.5111.y3.107rHL4.1.x3.7121.y3.244rHL4.1.x3.6561.y3.292rHL4.1.x3.6001.y3.3404.type6.bezier3.sid18.bezier_line_203148rHL6.4.datarL12.rHL4.1.x5.128.51.y3.675rHL4.1.x5.128.51.y3.600rHL4.1.x5.128.51.y3.525rHL4.1.x5.165.51.y3.454rHL4.1.x5.401.51.y3.454rHL4.1.x5.637.51.y3.454rHL4.1.x5.797.51.y3.481rHL4.1.x5.797.51.y3.583rHL4.1.x5.797.51.y3.685rHL4.1.x5.542.51.y3.726rHL4.1.x5.395.51.y3.726rHL4.1.x5.248.51.y3.7264.type6.bezier3.sid18.bezier_line_769516");
	////esb.trigger('render');
	
	
	esb.add({ 
				sid: 'html5_logo', 
				type: 'image', 	
				src: 'html.png',
	}).each(function(){ this.please_render(); });


$('.add').click(function(){ 
	if( !$(this).hasClass('active')	)
	{
		$(this).addClass('active');

		esb.bind_always('mousedown', esboza_studio.actions['bezier']['add_point'] );//в качестве параметра функции передаём esb.buffers['click'].list[0] - самый первый элемент по z-index'у, который попал в буфер esb.buffers['click']
		
	}
	else
	{
		$(this).removeClass('active');
		esb.unbind_always('mousedown');
	}
	return false;
});	

$('.save').click(function(){ 
	$.ajax({
				type: "GET",
				url: "http://192.168.1.101/esb.php?callback=?",
				dataType: "jsonp",
				//data: {work_objects_data: esboza_studio.actions['save'](), action:'save'},
				data: {work_objects_data: esb.exec('save'), action:'save'},
				crossDomain: true,
				jsonpCallback: 'jsonpCallback',
				success: function(msg){
						console.log('msg',msg);
				}
	 });
	///////////////////////
	
	/*var xhr = new XMLHttpRequest( );
	var someURL = "http://some-domain-here.com/some_resource_here.html";
	var params = "parameter=value goes here."
	xhr.open("POST", someURL, true);

	xhr.setRequestHeader("Content-type",   "application/x-www-form-urlencoded");
	xhr.setRequestHeader("Content-length", params.length);
	xhr.setRequestHeader("Connection",     "close");

	xhr.onerror = function( e ) 
	{
		alert( "Error processing XmlHttpRequest:  " + e.target.status );
	};
	xhr.onreadystatechange =function(){
		if(xhr.readyState == 4 && xhr.status == 200) 
		{
			alert(xhr.responseText);
		}
	};

	xhr.send(params);*/

	return false; 
});	
$('.load').click(function(){ 
		/*$.ajax({
		   url: "http://192.168.1.101/esb.php?callback=?",
		   dataType: "jsonp",
		   data: { action:'load' },
		   crossDomain: true,
		   jsonpCallback: 'jsonpCallback',
		 });*/
	 
		$.ajax({
				url: 'http://192.168.1.101/esb.php?callback=?',
				dataType: 'jsonp',
				data: { action:'load' },
				success: function(msg){  
						console.log(msg.work_objects_data); 
						/*esb.each(function(){ this.remove(); });*/
						this.model = Array();
						esb.list = Array();
						esboza_studio.actions['load']( msg.work_objects_data );
				}
		});
		

	return false; 
});	




esb.bind_default('click', function(){ 
										//если не нажата кнопка добавления новых точек, тогда, при клике на пустое место, опустошать esb.buffers['selected'] 
										if( !$('.add').hasClass('active') ){ 
												//esb.buffers['selected'].each(function(){				//скрываем контролы
												//		this.linked['controls'].each(function(){		//скрываем контролы
												//				this.status['VISIBLE'] = false;			//скрываем контролы
												//		});												//скрываем контролы
												//});														//скрываем контролы
												
												esb.buffers['selected'].each(function(){
													this.trigger('unselected');
												});
												esb.buffers['selected'] = new collection(); 			//очищаем список выделенных объектов
												
												esb.each(function(){ this.please_render(); });
										}; 
});
esb.bind_default('mousedown', function(){
											//клик по пустому месту
											esb.buffers['selected'].each(function(){
												this.trigger('unselected');
											});
											
											esb.buffers['selected'] = new collection(); 
});
									
									
									
									



